#ifndef ACUASLCD_H
#define ACUASLCD_H
/**
 @defgroup ACUAS_EPlcd ACUAS Easy Programming LCD

 @brief C macros to easily program the LCD of ACUAS ATmega16/ATmega32 board.
 @author Thomas Siepmann, Aachen University of Applied Sciences, Germany. Based on the LCD library of Peter Fleury http://jump.to/fleury
 @date 05.05.2009
 @see http://www.siepmann.fh-aachen.de
 \remarks
 Wiring of LCD (Displaytech 162 or 164A, Controller KS0070B.PCC and KS0063B.PCC): \n
 <tt>
LCD DB0 (Pin NO. 7) -> GND \n
LCD DB1 (Pin NO. 8) -> GND \n
LCD DB2 (Pin NO. 9) -> GND \n
LCD DB3 (Pin NO.10) -> GND \n
LCD DB4 (Pin NO.11) -> port D, pin4 \n
LCD DB5 (Pin NO.12) -> port D, pin5 \n
LCD DB6 (Pin NO.13) -> port D, pin6 \n
LCD DB7 (Pin NO.14) -> port D, pin7 \n
\n
LCD RS  (Pin NO. 4) -> port B, pin0 \n
LCD R/W (Pin NO. 5) -> port B, pin1 \n
LCD E   (Pin NO. 6) -> port D, pin2 \n
\n
Backlight LED (Pin NO. 15) -> port D, pin3 \n
</tt>
 \warning
* The ACUAS_LCD_TYPE_16xHD44780 controller type must be defined in projectdefinitions.h as
<tt>
* #define ACUAS_LCD_TYPE_164HD44780 // Displaytech 164A (4 x 16 characters) or
* #define ACUAS_LCD_TYPE_162HD44780 // Displaytech 164A (2 x 16 characters)
</tt>
*/
/**@{*/
/// @file ACUASlcd.h
/// @file ACUASlcd.c

#include <avr/io.h>
#include <stdlib.h>
#include <lcd.h>
#include <avr/wdt.h> // for assert reset (see ACUASlcd.c)

extern char lcd_str[21];

void LCDcharDef(uint8_t n,uint8_t row8 ,uint8_t row7 ,uint8_t row6,uint8_t row5,uint8_t row4,uint8_t row3,uint8_t row2, uint8_t row1);
void LCDbargraphV(long int yv, long int ymin, long int ymax, long int posx);

/**
 *  @brief   Display the assert message on the LCD. At cursor position 15/2 the countdown time is alternately appearing with the button number which stops the countdown. Push the button again to reset the device.

These macros must be defined in projectdefinitions.h:

NDEBUG: If defined supresses all asserts by conditional compilation.

__ASSERT_USE_STDERR: If defined assert displays an error message on LCD.

ASSERT_WAIT_SECS: When showing the assert message countdown in seconds before the device is resetted (by watchdog).

ASSERT_CONFIRM_BUTTON: Button by which the countdown can be stopped. Second push immediately resets the device.

 *  @param   function name of the invoking function
 *  @param   file name of the file where function is defined
 *  @param   line line number of the assert in file <file>
 *  @param   expression expression which evaluates to false
 *  @return  RESETS THE DEVICE (hardware reset)
 */
void assert_lcd(const char * function, const char * file, int line, const char * expression);

/**
 *  @name  LCD initialization and user defined characters
 *  User defined characters: start specialchar.exe in the Tools directory to interactively define characters
 */
/// Initializes the LCD and clears the screen
#define ACTIVATE_LCD {lcd_init(LCD_DISP_ON);lcd_init(LCD_DISP_ON);}
/// User defined characters with 1 additional row below (5x8 dots)
#define LCD_DEF(i,a,b,c,d,e,f,g,h) LCDcharDef(i,a,b,c,d,e,f,g,h);

/**
 *  @name  LCD Output
 */
/// Clear LCD screen
#define LCD_CLEAR lcd_clrscr();
/// Clear LCD screen. Obsolete, only for backward compatability
#define CLEAR_LCD LCD_CLEAR /// obsolete, only for backward compatability
/// Set cursor position to column x and row y
#define LCD_XY(x,y) lcd_gotoxy(((x)-1),((y)-1));
/// Write character at cursor position
#define LCD_CHAR(c) lcd_putc(c);
/// Write string at cursor position
#define LCD_TEXT(string) lcd_puts(string);
/// Write integer number at cursor position
#define LCD_NUMBER(v) {itoa( (v),lcd_str,10); lcd_puts(lcd_str);};
/**
 *  @brief   Write double precision number at cursor position.Conversion is done in the format "[-]d.ddd"
 *  @param   v double value to be displayed
 *  @param   w field width of the output string (including the . and the possible sign for negative values)
 *  @param   p number of digits after the decimal sign
 *  @return  none
 */
#define LCD_D_NUMBER(v,w,p) {dtostrf((v),w,p,lcd_str); lcd_puts(lcd_str);};
/// Write 1 character (char) at cursor position
#define LCD_CHAR(c) lcd_putc(c);
/// Switch on the LCD backlight (3-pin-jumper must be in lower position)
#define LCD_BACKLIGHT_OFF {(PORTD = PORTD & ~(1 << 3));}
/// Switch off the LCD backlight
#define LCD_BACKLIGHT_ON {(PORTD = PORTD | (1 << 3));}

/**
 *  @name  LCD vertical bargraph
 */
/// Define 8 user defined characters for bar representation
#define LCD_BAR_V_INIT {LCD_DEF(1,0,0,0,0,0,0,0,31) LCD_DEF(2,0,0,0,0,0,0,31,31) LCD_DEF(3,0,0,0,0,0,31,31,31) LCD_DEF(4,0,0,0,0,31,31,31,31) LCD_DEF(5,0,0,0,31,31,31,31,31) LCD_DEF(6,0,0,31,31,31,31,31,31) LCD_DEF(7,0,31,31,31,31,31,31,31) LCD_DEF(8,31,31,31,31,31,31,31,31)}
/**
 *  @brief   Display a vertical 2 line (16 rows) high bar.
 *  @param   y Value to be displayed
 *  @param   ymin Minimal value indicating the range of y
 *  @param   ymax Maximal value indicating the range of y
 *  @param   x Column where the bar should appear (1 based counting)
 *  @return  none
 */
#define LCD_BAR_V(y,ymin,ymax,x) LCDbargraphV(y,ymin,ymax,x);

/**
 *  @name  Assert messages on LCD
 *  Define the assert macro with extension of being displayed on the LCD for a specified amount of time before automatic reset of the device by the watchdog. Countdown can be stopped ba hitting a button.
 */
#if defined(NDEBUG)
#define assert(e)	((void)0) // replace assert by no operation
#else /* !NDEBUG */
#if defined(__ASSERT_USE_STDERR)
#define assert(e)	((e) ? (void)0 : assert_lcd(__func__, __FILE__, __LINE__, #e))
#else /* !__ASSERT_USE_STDERR */
#define assert(e)	((e) ? (void)0 : abort())
#endif /* __ASSERT_USE_STDERR */
#endif /* NDEBUG */

/**@}*/
#endif // ACUASLCD_H
